home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / EAT.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  39KB  |  1,536 lines

  1. /*      SCCS Id: @(#)eat.c      3.0     89/11/21
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"
  6. /*#define DEBUG     /* uncomment to enable new eat code debugging */
  7.  
  8. #ifdef DEBUG
  9. # ifdef WIZARD
  10. #define debug    if (wizard) pline
  11. # else
  12. #define debug    pline
  13. # endif
  14. #endif
  15.  
  16. STATIC_PTR int NDECL(Meatdone);
  17. STATIC_PTR int NDECL(eatfood);
  18. STATIC_PTR int NDECL(opentin);
  19. STATIC_PTR int NDECL(unfaint);
  20.  
  21. #ifdef OVLB
  22. static int FDECL(rounddiv, (long, int));
  23. static void FDECL(choke, (struct obj *));
  24. static void NDECL(recalc_wt);
  25. static struct obj *FDECL(touchfood, (struct obj *));
  26. static void NDECL(do_reset_eat);
  27. static void FDECL(done_eating, (BOOLEAN_P));
  28. static void FDECL(cprefx, (int));
  29. static void FDECL(cpostfx, (int));
  30. static void FDECL(start_tin, (struct obj *));
  31. static int FDECL(eatcorpse, (struct obj *));
  32. static void FDECL(start_eating, (struct obj *));
  33. static void FDECL(fprefx, (struct obj *));
  34. static void FDECL(fpostfx, (struct obj *));
  35. static int NDECL(bite);
  36.  
  37. #ifdef POLYSELF
  38. static int FDECL(rottenfood, (struct obj *));
  39. static void NDECL(eatspecial);
  40. static const char * FDECL(foodword, (struct obj *));
  41. #else
  42. static int NDECL(rottenfood);
  43. #endif /* POLYSELF */
  44.  
  45. char corpsename[60];
  46. char msgbuf[BUFSZ];
  47.  
  48. #endif /* OVLB */
  49.  
  50. /* hunger texts used on bottom line (each 8 chars long) */
  51. #define SATIATED    0
  52. #define NOT_HUNGRY    1
  53. #define HUNGRY        2
  54. #define WEAK        3
  55. #define FAINTING    4
  56. #define FAINTED        5
  57. #define STARVED        6
  58.  
  59. #ifdef OVLB
  60.  
  61. const char *hu_stat[] = {
  62.     "Satiated",
  63.     "        ",
  64.     "Hungry  ",
  65.     "Weak    ",
  66.     "Fainting",
  67.     "Fainted ",
  68.     "Starved "
  69. };
  70.  
  71. #endif /* OVLB */
  72.  
  73. #ifndef OVLB
  74.  
  75. STATIC_DCL const char NEARDATA comestibles[];
  76.  
  77. #else
  78.  
  79. STATIC_OVL const char NEARDATA comestibles[] = { FOOD_SYM, 0 };
  80. #ifdef POLYSELF
  81. STATIC_OVL const char NEARDATA everything[] = { GOLD_SYM, /* must come first */
  82.     WEAPON_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM,
  83. # ifdef SPELLS
  84.     SPBOOK_SYM,
  85. # endif
  86.     RING_SYM, WAND_SYM, AMULET_SYM, FOOD_SYM, TOOL_SYM, GEM_SYM,
  87.     ROCK_SYM, BALL_SYM, CHAIN_SYM, 0 };
  88.  
  89. #endif /* POLYSELF */
  90. #endif /* OVLB */
  91. #ifdef OVL1
  92. # ifdef POLYSELF
  93.  
  94. boolean
  95. is_edible(obj)
  96. register struct obj *obj;
  97. {
  98.     if (metallivorous(uasmon) && (obj->olet == GOLD_SYM ||
  99.             (objects[obj->otyp].oc_material > WOOD &&
  100.             objects[obj->otyp].oc_material < MINERAL)))
  101.         return TRUE;
  102.     if (u.umonnum == PM_GELATINOUS_CUBE &&
  103.             objects[obj->otyp].oc_material <= WOOD)
  104.         return TRUE;
  105.     return !!index(comestibles, obj->olet);
  106. }
  107. # endif /* POLYSELF */
  108. #endif /* OVL1 */
  109. #ifdef OVLB
  110.  
  111. /* calculate x/y, rounding as appropriate */
  112.  
  113. static int
  114. rounddiv(x, y)
  115. long x;
  116. int y;
  117. {
  118.     int divsgn = 1;
  119.     int r, m;
  120.  
  121.     if (y == 0)
  122.         panic("division by zero in rounddiv");
  123.     if (x < 0) {
  124.         divsgn = -divsgn; x = -x;
  125.     }
  126.     if (y < 0) {
  127.         divsgn = -divsgn; y = -y;
  128.     }
  129.     r = x/y;
  130.     m = x%y;
  131.     if (2*m >= y)
  132.         r++;
  133.     return divsgn*r;
  134. }
  135.  
  136. void
  137. init_uhunger(){
  138.     u.uhunger = 900;
  139.     u.uhs = NOT_HUNGRY;
  140. }
  141.  
  142. const struct { const char *txt; int nut; } tintxts[] = {
  143.     "deep fried",    60,
  144.     "pickled",    40,
  145.     "soup made from", 20,
  146.     "pureed", 500,
  147.     "rotten", -50,
  148.     "",    0
  149. };
  150. #define    TTSZ    SIZE(tintxts)
  151.  
  152. static struct {
  153.     struct    obj *tin;
  154.     int    usedtime, reqtime;
  155. } NEARDATA tin;
  156.  
  157. static struct {
  158.     struct    obj *piece;    /* the thing being eaten, or last thing that
  159.                  * was partially eaten, unless that thing was
  160.                  * a tin, which uses the tin structure above */
  161.     int    usedtime,    /* turns spent eating */
  162.         reqtime;    /* turns required to eat */
  163.     int    nmod;        /* coded nutrition per turn */
  164.     Bitfield(canchoke,1);    /* was satiated at beginning */
  165.     Bitfield(fullwarn,1);    /* have warned about being full */
  166.     Bitfield(eating,1);    /* victual currently being eaten */
  167.     Bitfield(doreset,1);    /* stop eating at end of turn */
  168. } NEARDATA victual;
  169.  
  170. STATIC_PTR
  171. int
  172. Meatdone() {        /* called after mimicing is over */
  173.     u.usym =
  174. #ifdef POLYSELF
  175.         u.mtimedone ? uasmon->mlet :
  176. #endif
  177.         S_HUMAN;
  178.     prme();
  179.     return 0;
  180. }
  181.  
  182. /* Created by GAN 01/28/87
  183.  * Amended by AKP 09/22/87: if not hard, don't choke, just vomit.
  184.  * Amended by 3.  06/12/89: if not hard, sometimes choke anyway, to keep risk.
  185.  *          11/10/89: if hard, rarely vomit anyway, for slim chance.
  186.  */
  187. /*ARGSUSED*/
  188. static void
  189. choke(food)    /* To a full belly all food is bad. (It.) */
  190.     register struct obj *food;
  191. {
  192.     /* only happens if you were satiated */
  193.     if(u.uhs != SATIATED) return;
  194.  
  195.     if (pl_character[0] == 'K' && u.ualigntyp == U_LAWFUL)
  196.         u.ualign--;    /* gluttony is unchivalrous */
  197.  
  198. #ifdef HARD
  199.     if (!rn2(20)) {
  200. #else
  201.     if (rn2(20)) {
  202. #endif
  203.         You("stuff yourself and then vomit voluminously.");
  204.         morehungry(1000);    /* you just got *very* sick! */
  205.         vomit();
  206.     } else {
  207.         killer_format = KILLED_BY_AN;
  208.         if(food) {
  209. #ifdef POLYSELF
  210.             if (food->olet == GOLD_SYM) {
  211.                 killer_format = KILLED_BY;
  212.                 killer = "eating too rich a meal";
  213.             } else
  214. #endif
  215.                 killer = singular(food, xname);
  216.         } else
  217.             killer = "exuberant appetite";
  218.         if (!food) You("choke over it.");
  219. #ifdef POLYSELF
  220.         else You("choke over your %s.", foodword(food));
  221. #else
  222.         else You("choke over your food.");
  223. #endif
  224.         You("die...");
  225.         done(CHOKING);
  226.     }
  227. }
  228.  
  229. static void
  230. recalc_wt() {    /* modify object wt. depending on time spent consuming it */
  231.     register struct obj *piece = victual.piece;
  232.  
  233. #ifdef DEBUG
  234.     debug("Old weight = %d", piece->owt);
  235.     debug("Used time = %d, Req'd time = %d",
  236.         victual.usedtime, victual.reqtime);
  237. #endif
  238.     /* weight(piece) = weight of full item */
  239.       if(victual.usedtime)
  240.         piece->owt = eaten_stat(weight(piece), piece);
  241. #ifdef DEBUG
  242.     debug("New weight = %d", piece->owt);
  243. #endif
  244. }
  245.  
  246. void
  247. reset_eat() {        /* called when eating interrupted by an event */
  248.  
  249.     /* we only set a flag here - the actual reset process is done after
  250.      * the round is spent eating.
  251.      */
  252.     if(victual.eating && !victual.doreset) {
  253. #ifdef DEBUG
  254.         debug("reset_eat...");
  255. #endif
  256.         victual.doreset = TRUE;
  257.     }
  258.     return;
  259. }
  260.  
  261. static struct obj *
  262. touchfood(otmp)
  263. register struct obj *otmp;
  264. {
  265.     if (otmp->quan > 1) {
  266.         otmp = splitobj(otmp, (int)otmp->quan-1);
  267. #ifdef DEBUG
  268.         debug("split object,");
  269. #endif
  270.     }
  271.     if (!otmp->oeaten)
  272.         otmp->oeaten = (otmp->otyp == CORPSE ?
  273.                 (int)mons[otmp->corpsenm].cnutrit :
  274.                 objects[otmp->otyp].nutrition);
  275.     if (carried(otmp)) {
  276.         freeinv(otmp);
  277.         if(inv_cnt() >= 52)
  278.         dropy(otmp);
  279.         else
  280.         otmp = addinv(otmp); /* unlikely but a merge is possible */
  281.     }
  282.     return(otmp);
  283. }
  284.  
  285. /* When food decays, in the middle of your meal, we don't want to dereference
  286.  * any dangling pointers, so set it to null (which should still trigger
  287.  * do_reset_eat() at the beginning of eatfood()) and check for null pointers
  288.  * in do_reset_eat().
  289.  */
  290. void
  291. food_disappears(obj)
  292. register struct obj *obj;
  293. {
  294.     if (obj == victual.piece) victual.piece = (struct obj *)0;
  295. }
  296.  
  297. static void
  298. do_reset_eat() {
  299.  
  300. #ifdef DEBUG
  301.     debug("do_reset_eat...");
  302. #endif
  303.     if (victual.piece) {
  304.         victual.piece = touchfood(victual.piece);
  305.         recalc_wt();
  306.     }
  307.     victual.fullwarn = victual.eating = victual.doreset = FALSE;
  308.     /* Do not set canchoke to FALSE; if we continue eating the same object
  309.      * we need to know if canchoke was set when they started eating it the
  310.      * previous time.  And if we don't continue eating the same object
  311.      * canchoke always gets recalculated anyway.
  312.      */
  313.     stop_occupation();
  314. }
  315.  
  316. STATIC_PTR
  317. int
  318. eatfood() {        /* called each move during eating process */
  319.     if(!carried(victual.piece) && !obj_here(victual.piece, u.ux, u.uy)) {
  320.         /* maybe it was stolen? */
  321.         do_reset_eat();
  322.         return(0);
  323.     }
  324.     if(!victual.eating) return(0);
  325.  
  326.     if(++victual.usedtime < victual.reqtime) {
  327.         if(bite()) return(0);
  328.         return(1);    /* still busy */
  329.     } else {    /* done */
  330.         done_eating(TRUE);
  331.         return(0);
  332.     }
  333. }
  334.  
  335. static void
  336. done_eating(message)
  337. boolean message;
  338. {
  339. #ifndef NO_SIGNAL
  340.     victual.piece->in_use = TRUE;
  341. #endif
  342.     if (nomovemsg) {
  343.         if (message) pline(nomovemsg);
  344.         nomovemsg = 0;
  345.     } else if (message)
  346.         You("finish eating the %s.", singular(victual.piece, xname));
  347.  
  348.     if(victual.piece->otyp == CORPSE)
  349.         cpostfx(victual.piece->corpsenm);
  350.     else
  351.         fpostfx(victual.piece);
  352.  
  353.     if (carried(victual.piece)) useup(victual.piece);
  354.     else useupf(victual.piece);
  355.     victual.piece = (struct obj *) 0;
  356.     victual.fullwarn = victual.eating = victual.doreset = FALSE;
  357. }
  358.  
  359. static void
  360. cprefx(pm)        /* called at the "first bite" of a corpse */
  361. register int pm;
  362. {
  363.     if ((pl_character[0]=='E') ? is_elf(&mons[pm]) : is_human(&mons[pm])) {
  364.         You("cannibal!  You will regret this!");
  365.         Aggravate_monster |= INTRINSIC;
  366.     }
  367.  
  368.     switch(pm) {
  369.         case PM_LITTLE_DOG:
  370.         case PM_DOG:
  371.         case PM_LARGE_DOG:
  372.         case PM_KITTEN:
  373.         case PM_HOUSECAT:
  374.         case PM_LARGE_CAT:
  375.         Aggravate_monster |= INTRINSIC;
  376.         break;
  377.         case PM_COCKATRICE:
  378. #ifdef MEDUSA
  379.         case PM_MEDUSA:
  380. #endif
  381. #ifdef POLYSELF
  382.         if(!resists_ston(uasmon))
  383. #endif
  384.             {
  385.             char *cruft;    /* killer is const char * */
  386.             killer_format = KILLED_BY;
  387.             killer = cruft = (char *) alloc(40);
  388.             You("turn to stone.");
  389.             Sprintf(cruft, "%s meat", mons[pm].mname);
  390.             done(STONING);
  391.             }
  392.             break;
  393. #ifdef POLYSELF
  394.         case PM_LIZARD:
  395.         /* Relief from cockatrices -dgk */
  396.         if (Stoned) {
  397.             Stoned = 0;
  398.             You("feel limber!");
  399.         }
  400.         break;
  401.         default:
  402.         if(acidic(&mons[pm]) && Stoned) {
  403.             pline("What a pity - you just destroyed a future piece of art!");
  404.             Stoned = 0;
  405.         }
  406. #endif
  407.     }
  408.     return;
  409. }
  410.  
  411. static void
  412. cpostfx(pm)        /* called after completely consuming a corpse */
  413. register int pm;
  414. {
  415.     register int tmp = 0;
  416.  
  417.     switch(pm) {
  418.         case PM_WRAITH:
  419.         pluslvl();
  420.         break;
  421. #ifdef POLYSELF
  422.         case PM_WERERAT:
  423.         u.ulycn = PM_RATWERE;
  424.         break;
  425.         case PM_WEREJACKAL:
  426.         u.ulycn = PM_JACKALWERE;
  427.         break;
  428.         case PM_WEREWOLF:
  429.         u.ulycn = PM_WOLFWERE;
  430.         break;
  431. #endif
  432.         case PM_NURSE:
  433.         u.uhp = u.uhpmax;
  434.         flags.botl = 1;
  435.         break;
  436.         case PM_STALKER:
  437.         if(!Invis) {
  438.             HInvis = 50+rn2(100);
  439.             if(!See_invisible)
  440.                 newsym(u.ux, u.uy);
  441.         } else {
  442.             if (!(HInvis & INTRINSIC)) You("feel hidden!");
  443.             HInvis |= INTRINSIC;
  444.             HSee_invisible |= INTRINSIC;
  445.         }
  446.         /* fall into next case */
  447.         case PM_YELLOW_LIGHT:
  448.         /* fall into next case */
  449.         case PM_GIANT_BAT:
  450.         make_stunned(HStun + 30,FALSE);
  451.         /* fall into next case */
  452.         case PM_BAT:
  453.         make_stunned(HStun + 30,FALSE);
  454.         break;
  455.         case PM_GIANT_MIMIC:
  456.         tmp += 10;
  457.         /* fall into next case */
  458.         case PM_LARGE_MIMIC:
  459.         tmp += 20;
  460.         /* fall into next case */
  461.         case PM_SMALL_MIMIC:
  462.         tmp += 20;
  463.         if(u.usym == S_HUMAN) {
  464.             You("cannot resist the temptation to mimic a pile of gold.");
  465.             nomul(-tmp);
  466.             afternmv = Meatdone;
  467.             if (pl_character[0]=='E')
  468.             nomovemsg = "You now again prefer mimicking an elf.";
  469.             else
  470.             nomovemsg = "You now again prefer mimicking a human.";
  471.             u.usym = GOLD_SYM;
  472.             prme();
  473.         }
  474.         break;
  475.         case PM_FLOATING_EYE:
  476.         if (!(HTelepat & INTRINSIC)) {
  477.             HTelepat |= INTRINSIC;
  478.             You("feel a %s mental acuity.",
  479.             Hallucination ? "normal" : "strange");
  480.         }
  481.         break;
  482.         case PM_QUANTUM_MECHANIC:
  483.         Your("velocity suddenly seems very uncertain!");
  484.         if (Fast & INTRINSIC) {
  485.             Fast &= ~INTRINSIC;
  486.             You("seem slower.");
  487.         } else {
  488.             Fast |= INTRINSIC;
  489.             You("seem faster.");
  490.         }
  491.         break;
  492.         case PM_LIZARD:
  493.         if (HStun > 2)  make_stunned(2L,FALSE);
  494.         if (HConfusion > 2)  make_confused(2L,FALSE);
  495.         break;
  496.         case PM_CHAMELEON:
  497.         You("feel a change coming over you.");
  498. #ifdef POLYSELF
  499.         polyself();
  500. #else
  501.         newman();
  502. #endif
  503.         break;
  504.         default: {
  505.         register struct permonst *ptr = &mons[pm];
  506.         if(dmgtype(ptr, AD_STUN) || ptr==&mons[PM_VIOLET_FUNGUS]) {
  507.             pline ("Oh wow!  Great stuff!");
  508.             make_hallucinated(Hallucination + 200,FALSE);
  509.         }
  510.         /* prevent polymorph abuse by killing/eating your offspring */
  511.         if(ptr >= &mons[PM_BABY_GRAY_DRAGON] &&
  512.            ptr <= &mons[PM_BABY_YELLOW_DRAGON]) return;
  513.         if(is_giant(ptr)) gainstr((struct obj *)0, 0);
  514.  
  515.         if(can_teleport(ptr) && ptr->mlevel > rn2(10)) {
  516.             if (!(HTeleportation & INTRINSIC)) {
  517.             You("feel very jumpy.");
  518.             HTeleportation |= INTRINSIC;
  519.             }
  520.         } else if(control_teleport(ptr) && ptr->mlevel > rn2(15)) {
  521.             if (!(HTeleport_control & INTRINSIC)) {
  522.             You("feel in control of yourself.");
  523.             HTeleport_control |= INTRINSIC;
  524.             }
  525.         } else if(resists_fire(ptr) && ptr->mlevel > rn2(15)) {
  526.             if (!(HFire_resistance & INTRINSIC)) {
  527.             You("feel a momentary chill.");
  528.             HFire_resistance |= INTRINSIC;
  529.             }
  530.         } else if(resists_cold(ptr) && ptr->mlevel > rn2(15)) {
  531.             if (!(HCold_resistance & INTRINSIC)) {
  532.             You("feel full of hot air.");
  533.             HCold_resistance |= INTRINSIC;
  534.             }
  535.         } else if(((ptr->mflags1 & M1_POIS_RES) && ptr->mlevel>rn2(15))
  536.            || ((pm == PM_KILLER_BEE || pm == PM_SCORPION) && !rn2(4))) {
  537.         /* Monsters with only M1_POIS are poison resistant themselves,
  538.          * but do not confer resistance when eaten
  539.          */
  540.             if (!(HPoison_resistance & INTRINSIC)) {
  541.             You("feel healthy.");
  542.             HPoison_resistance |= INTRINSIC;
  543.             }
  544.         } else if(resists_elec(ptr) && ptr->mlevel > rn2(15)) {
  545.             if (!(HShock_resistance & INTRINSIC)) {
  546.             Your("health currently feels amplified!");
  547.             HShock_resistance |= INTRINSIC;
  548.             }
  549.         } else if((ptr->mflags1 & M1_SLEE_RES) && ptr->mlevel > rn2(15)) {
  550.         /* Undead monsters never sleep,
  551.          * but also do not confer resistance when eaten
  552.          */
  553.             if (!(HSleep_resistance & INTRINSIC)) {
  554.             You("feel wide awake.");
  555.             HSleep_resistance |= INTRINSIC;
  556.             }
  557.         } else if(resists_disint(ptr) && ptr->mlevel > rn2(15)) {
  558.             if (!(HDisint_resistance & INTRINSIC)) {
  559.             You("feel very firm.");
  560.             HDisint_resistance |= INTRINSIC;
  561.             }
  562.         }
  563.         }
  564.         break;
  565.     }
  566.     return;
  567. }
  568.  
  569. STATIC_PTR
  570. int
  571. opentin()        /* called during each move whilst opening a tin */
  572. {
  573.     register int r;
  574.  
  575.     if(!carried(tin.tin) && !obj_here(tin.tin, u.ux, u.uy))
  576.                     /* perhaps it was stolen? */
  577.         return(0);        /* %% probably we should use tinoid */
  578.     if(tin.usedtime++ >= 50) {
  579.         You("give up your attempt to open the tin.");
  580.         return(0);
  581.     }
  582.     if(tin.usedtime < tin.reqtime)
  583.         return(1);        /* still busy */
  584.     if(tin.tin->cursed && tin.tin->spe != -1 && !rn2(8)) {
  585.         b_trapped("tin");
  586.         goto use_me;
  587.     }
  588.     You("succeed in opening the tin.");
  589.     if(tin.tin->spe != 1) {
  590.         if(tin.tin->corpsenm == -1) {
  591.         pline("It turns out to be empty.");
  592.         tin.tin->dknown = tin.tin->known = TRUE;
  593.         goto use_me;
  594.         }
  595.         r = tin.tin->cursed ? 4 : rn2(TTSZ-1); /* Always rotten if cursed */
  596. #ifdef MACOS
  597.     {
  598.         char tmp[128];
  599.         if(!flags.silent) SysBeep(20);
  600.         Sprintf(tmp, "It smells like %s. Eat it ?", makeplural(
  601.           Hallucination ? rndmonnam() : mons[tin.tin->corpsenm].mname));
  602.         if(UseMacAlertText(128, tmp) == 2) {
  603. #else
  604.         pline("It smells like %s.", makeplural(
  605.           Hallucination ? rndmonnam() : mons[tin.tin->corpsenm].mname));
  606.         pline("Eat it? ");
  607.         if (yn() == 'n') {
  608. #endif
  609.         if (!Hallucination) tin.tin->dknown = tin.tin->known = TRUE;
  610.         if (flags.verbose) You("discard the open tin.");
  611.         goto use_me;
  612.         }
  613. #ifdef MACOS
  614.     }
  615. #endif
  616.         You("consume %s %s.", tintxts[r].txt,
  617.           mons[tin.tin->corpsenm].mname);
  618.         tin.tin->dknown = tin.tin->known = TRUE;
  619.         cprefx(tin.tin->corpsenm); cpostfx(tin.tin->corpsenm);
  620.  
  621.         /* check for vomiting added by GAN 01/16/87 */
  622.         if(tintxts[r].nut < 0) make_vomiting((long)rn1(15,10), FALSE);
  623.         else lesshungry(tintxts[r].nut);
  624.  
  625.         if(r == 0) {            /* Deep Fried */
  626.         Glib = rnd(15);
  627.         pline("Eating deep fried food made your %s very slippery.",
  628.             makeplural(body_part(FINGER)));
  629.         }
  630.     } else {
  631. #ifdef MACOS
  632.     {
  633.         char tmp[128];
  634.         if(!flags.silent) SysBeep(20);
  635.         if (tin.tin->cursed)
  636.         Sprintf(tmp, "It contains some decaying %s substance. Eat it ?",
  637.             Hallucination ? hcolor() : green);
  638.         else
  639.         Sprintf(tmp, "It contains spinach. Eat it ?");
  640.         if(UseMacAlertText(128, tmp) == 2) {
  641. #else
  642.         if (tin.tin->cursed)
  643.         pline("It contains some decaying %s substance.",
  644.             Hallucination ? hcolor() : green);
  645.         else
  646.         pline("It contains spinach.");
  647.  
  648.         pline("Eat it? ");
  649.         if (yn() == 'n') {
  650. #endif
  651.         if (!Hallucination && !tin.tin->cursed)
  652.             tin.tin->dknown = tin.tin->known = TRUE;
  653.         if (flags.verbose)
  654.             You("discard the open tin.");
  655.         goto use_me;
  656.         }
  657. #ifdef MACOS
  658.     }
  659. #endif
  660.         if (!tin.tin->cursed)
  661.         pline("This makes you feel like %s!",
  662.               Hallucination ? "Swee'pea" : "Popeye");
  663.         lesshungry(600);
  664.         gainstr(tin.tin, 0);
  665.     }
  666.     tin.tin->dknown = tin.tin->known = TRUE;
  667. use_me:
  668.     if (carried(tin.tin)) useup(tin.tin);
  669.     else useupf(tin.tin);
  670.     return(0);
  671. }
  672.  
  673. static void
  674. start_tin(otmp)        /* called when starting to open a tin */
  675.     register struct obj *otmp;
  676. {
  677.     register int tmp;
  678.  
  679. #ifdef POLYSELF
  680.     if (metallivorous(uasmon)) {
  681.         You("bite right into the metal can....");
  682.         tmp = 1;
  683.     } else
  684. #endif
  685.     if (otmp->blessed) {
  686.         pline("The tin opens like magic!");
  687.         tmp = 1;
  688.     } else if(uwep) {
  689.         switch(uwep->otyp) {
  690.         case TIN_OPENER:
  691.             tmp = 1;
  692.             break;
  693.         case DAGGER:
  694. #ifdef TOLKIEN
  695.         case ELVEN_DAGGER:
  696.         case ORCISH_DAGGER:
  697. #endif
  698.         case ATHAME:
  699. #ifdef WORM
  700.         case CRYSKNIFE:
  701. #endif
  702.             tmp = 3;
  703.             break;
  704.         case PICK_AXE:
  705.         case AXE:
  706.             tmp = 6;
  707.             break;
  708.         default:
  709.             goto no_opener;
  710.         }
  711.         pline("Using your %s you try to open the tin.",
  712.             aobjnam(uwep, NULL));
  713.     } else {
  714. no_opener:
  715.         pline("It is not so easy to open this tin.");
  716.         if(Glib) {
  717.             pline("The tin slips out of your hands.");
  718.             if(otmp->quan > 1) {
  719.                 register struct obj *obj;
  720.                 obj = splitobj(otmp, 1);
  721.                 if(otmp == uwep) setuwep(obj);
  722.             }
  723.             if (carried(otmp)) dropx(otmp);
  724.             else stackobj(otmp);
  725.             return;
  726.         }
  727.         tmp = 10 + rn2(1 + 500/((int)(ACURR(A_DEX) + ACURR(A_STR))));
  728.     }
  729.     tin.reqtime = tmp;
  730.     tin.usedtime = 0;
  731.     tin.tin = otmp;
  732.     set_occupation(opentin, "opening the tin", 0);
  733.     return;
  734. }
  735.  
  736. int
  737. Hear_again() {        /* called when waking up after fainting */
  738.     flags.soundok = 1;
  739.     return 0;
  740. }
  741.  
  742. static int
  743. #ifdef POLYSELF
  744. rottenfood(obj)
  745. struct obj *obj;
  746. #else
  747. rottenfood()
  748. #endif
  749. {        /* called on the "first bite" of rotten food */
  750. #ifdef POLYSELF
  751.     pline("Blecch!  Rotten %s!", foodword(obj));
  752. #else
  753.     pline("Blecch!  Rotten food!");
  754. #endif
  755.     if(!rn2(4)) {
  756.         if (Hallucination) You("feel rather trippy.");
  757.         else You("feel rather %s.", body_part(LIGHT_HEADED));
  758.         make_confused(HConfusion + d(2,4),FALSE);
  759.     } else if(!rn2(4) && !Blind) {
  760.         pline("Everything suddenly goes dark.");
  761.         make_blinded((long)d(2,10),FALSE);
  762.     } else if(!rn2(3)) {
  763.         if(Blind)
  764.           pline("The world spins and you slap against the floor.");
  765.         else
  766.           pline("The world spins and goes dark.");
  767.         flags.soundok = 0;
  768.         nomul(-rnd(10));
  769.         nomovemsg = "You are conscious again.";
  770.         afternmv = Hear_again;
  771.         return(1);
  772.     }
  773.     return(0);
  774. }
  775.  
  776. static int
  777. eatcorpse(otmp)        /* called when a corpse is selected as food */
  778.     register struct obj *otmp;
  779. {
  780.     register const char *cname = mons[otmp->corpsenm].mname;
  781.     register int tp, rotted = 0;
  782.  
  783.     tp = 0;
  784.  
  785.     if(otmp->corpsenm != PM_LIZARD) {
  786. #ifndef LINT    /* problem if more than 320K moves before try to eat */
  787.         rotted = (monstermoves - otmp->age)/((long)(10 + rn2(20)));
  788. #endif
  789.  
  790.         if(otmp->cursed) rotted += 2;
  791.         else if (otmp->blessed) rotted -= 2;
  792.     }
  793.  
  794.     if(otmp->corpsenm != PM_ACID_BLOB && (rotted > 5)) {
  795.         tp++;
  796.         pline("Ulch - that %s was tainted!",
  797.               mons[otmp->corpsenm].mlet != S_FUNGUS ?
  798.                 "meat" : "fungoid vegetation");
  799. #ifdef POLYSELF
  800.         if (u.usym == S_FUNGUS)
  801.             pline("It doesn't seem at all sickening, though...");
  802.         else {
  803. #endif
  804.             make_sick(10L + rn2(10),FALSE);
  805.             Sprintf(corpsename, "rotted %s corpse", cname);
  806.             u.usick_cause = (const char *)corpsename;
  807.             flags.botl = 1;
  808. #ifdef POLYSELF
  809.         }
  810. #endif
  811.         if (carried(otmp)) useup(otmp);
  812.         else useupf(otmp);
  813.         return(1);
  814.     } else if(acidic(&mons[otmp->corpsenm])
  815. #ifdef POLYSELF
  816.           && !resists_acid(uasmon)
  817. #endif
  818.          ) {
  819.         tp++;
  820.         You("have a very bad case of stomach acid.");
  821.         losehp(rnd(15), "acidic corpse", KILLED_BY_AN);
  822.     } else if(poisonous(&mons[otmp->corpsenm]) && rn2(5)) {
  823.         tp++;
  824.         pline("Ecch - that must have been poisonous!");
  825.         if(!Poison_resistance) {
  826.             losestr(rnd(4));
  827.             losehp(rnd(15), "poisonous corpse", KILLED_BY_AN);
  828.         } else    You("seem unaffected by the poison.");
  829.     /* now any corpse left too long will make you mildly ill */
  830.     } else if(((rotted > 5) || ((rotted > 3) && rn2(5)))
  831. #ifdef POLYSELF
  832.         && u.usym != S_FUNGUS
  833. #endif
  834.                             ){
  835.         tp++;
  836.         You("feel%s sick.", (Sick) ? " very" : "");
  837.         losehp(rnd(8), "cadaver", KILLED_BY_AN);
  838.     }
  839.     if(!tp && otmp->corpsenm != PM_LIZARD && (otmp->orotten || !rn2(7))) {
  840. #ifdef POLYSELF
  841.         if(rottenfood(otmp)) {
  842. #else
  843.         if(rottenfood()) {
  844. #endif
  845.         otmp->orotten = TRUE;
  846.         (void)touchfood(otmp);
  847.         return(1);
  848.         }
  849.         otmp->oeaten >>= 2;
  850.     } else {
  851. #ifdef POLYSELF
  852.         pline("This %s corpse %s!", cname,
  853.         carnivorous(uasmon) ? "is delicious" : "tastes terrible");
  854. #else
  855.         pline("This %s corpse tastes terrible!", cname);
  856. #endif
  857.     }
  858.  
  859.     /* delay is weight dependent */
  860.     victual.reqtime = 3 + (mons[otmp->corpsenm].cwt >> 2);
  861.     return(0);
  862. }
  863.  
  864. static void
  865. start_eating(otmp)        /* called as you start to eat */
  866.     register struct obj *otmp;
  867. {
  868. #ifdef DEBUG
  869.     debug("start_eating: %lx (victual = %lx)", otmp, victual.piece);
  870.     debug("reqtime = %d", victual.reqtime);
  871.     debug("(original reqtime = %d)", objects[otmp->otyp].oc_delay);
  872.     debug("nmod = %d", victual.nmod);
  873.     debug("oeaten = %d", otmp->oeaten);
  874. #endif
  875.     victual.fullwarn = victual.doreset = FALSE;
  876.     victual.eating = TRUE;
  877.  
  878.     if (otmp->otyp == CORPSE)
  879.         cprefx(victual.piece->corpsenm);
  880.  
  881.     if (bite()) return;
  882.  
  883.     if(++victual.usedtime >= victual.reqtime) {
  884.         done_eating(FALSE);
  885.         return;
  886.     }
  887.  
  888.     Sprintf(msgbuf, "eating the %s", singular(otmp, xname));
  889.     set_occupation(eatfood, msgbuf, 0);
  890. }
  891.  
  892.  
  893. static void
  894. fprefx(otmp)        /* called on "first bite" of (non-corpse) food */
  895.  
  896.     register struct obj *otmp;
  897. {
  898.     switch(otmp->otyp) {
  899.  
  900.         case FOOD_RATION:
  901.         if(u.uhunger <= 200)
  902.             if (Hallucination) pline("Oh wow, like, superior, man!");
  903.             else           pline("That food really hit the spot!");
  904.         else if(u.uhunger <= 700) pline("That satiated your stomach!");
  905.         break;
  906.         case TRIPE_RATION:
  907. #ifdef POLYSELF
  908.         if (carnivorous(uasmon))
  909.             pline("That tripe ration was surprisingly good!");
  910.         else {
  911. #endif
  912.             pline("Yak - dog food!");
  913.             more_experienced(1,0);
  914.             flags.botl = 1;
  915. #ifdef POLYSELF
  916.         }
  917. #endif
  918.         if(rn2(2)
  919. #ifdef POLYSELF
  920.             && !carnivorous(uasmon)
  921. #endif
  922.                         ) {
  923.             make_vomiting((long)rn1(victual.reqtime, 10), FALSE);
  924.         }
  925.         break;
  926. #ifdef POLYSELF
  927.         case CLOVE_OF_GARLIC:
  928.         if (is_undead(uasmon)) {
  929.             make_vomiting((long)rn1(victual.reqtime, 5), FALSE);
  930.             break;
  931.         }
  932.         /* Fall through otherwise */
  933. #endif
  934.         default:
  935. #ifdef TUTTI_FRUTTI
  936.         if (otmp->otyp==SLIME_MOLD && !otmp->cursed
  937.             && otmp->spe == current_fruit)
  938.             pline(!Hallucination ? "Mmm!  Your favorite!" :
  939.                            "Yum!  Your fave fruit!");
  940.         else
  941. #endif
  942. #ifdef UNIX
  943.         if (otmp->otyp == APPLE || otmp->otyp == PEAR) {
  944.             if (!Hallucination) pline("Core dumped.");
  945.             else {
  946. /* This is based on an old Usenet joke, a fake a.out manual page */
  947.             int x = rnd(100);
  948.             if (x <= 75)
  949.                 pline("Segmentation fault -- core dumped.");
  950.             else if (x <= 99)
  951.                 pline("Bus error -- core dumped.");
  952.             else pline("Yo' mama -- core dumped.");
  953.             }
  954.         } else 
  955. #endif
  956.         {
  957.             unsigned oldquan = otmp->quan;
  958.             otmp->quan = 1;
  959.             pline("This %s is %s!", xname(otmp),
  960.               otmp->cursed ? (Hallucination ? "grody" : "terrible"):
  961.               Hallucination ? "gnarly" : (
  962. #ifdef TOLKIEN
  963.                otmp->otyp==CRAM_RATION ? "bland":
  964. #endif
  965.                "delicious"));
  966.             otmp->quan = oldquan;
  967.         }
  968.         break;
  969.     }
  970. }
  971.  
  972. #ifdef POLYSELF
  973. static void
  974. eatspecial() /* called after eating non-food */
  975. {
  976.     register struct obj *otmp = victual.piece;
  977.  
  978.     lesshungry(victual.nmod);
  979.     victual.piece = (struct obj *)0;
  980.     victual.eating = 0;
  981.     if (otmp->olet == GOLD_SYM) { /* temporary gold object */
  982.         free ((genericptr_t)otmp);
  983.         return;
  984.     }
  985.     if (otmp->olet == POTION_SYM) {
  986.         otmp->quan++; /* dopotion() does a useup() */
  987. #ifdef MACOS
  988.         segments |= SEG_EAT;
  989. #endif
  990.         (void)dopotion(otmp);
  991.     }
  992.     if (otmp == uball) unpunish();
  993.     if (otmp == uchain) unpunish(); /* but no useup() */
  994.     else if (carried(otmp)) useup(otmp);
  995.     else useupf(otmp);
  996. }
  997.  
  998. static const char *
  999. foodword(otmp)
  1000. register struct obj *otmp;
  1001. {
  1002.     if (otmp->olet == FOOD_SYM) return "food";
  1003.     if (otmp->olet == GOLD_SYM) return "gold";
  1004.     if (objects[otmp->otyp].oc_material == GLASS) {
  1005.         if (otmp->olet == GEM_SYM && otmp->dknown)
  1006.             makeknown(otmp->otyp);
  1007.         return "glass";
  1008.     }
  1009.     if (objects[otmp->otyp].oc_material > WOOD &&
  1010.             objects[otmp->otyp].oc_material < MINERAL)
  1011.         return "metal";
  1012.     if (objects[otmp->otyp].oc_material == MINERAL)
  1013.         return (otmp->otyp <= LAST_GEM && otmp->olet == GEM_SYM)
  1014.             ? "rich food" : "stone";
  1015.     if (objects[otmp->otyp].oc_material == WOOD) return "wood";
  1016.     if (otmp->olet == ARMOR_SYM) return "armor";
  1017.     return "stuff";
  1018. }
  1019. #endif
  1020.  
  1021. static void
  1022. fpostfx(otmp)        /* called after consuming (non-corpse) food */
  1023.  
  1024.     register struct obj *otmp;
  1025. {
  1026.     switch(otmp->otyp) {
  1027. #ifdef POLYSELF
  1028.         case CLOVE_OF_GARLIC:
  1029.         if (u.ulycn != -1) {
  1030.             u.ulycn = -1;
  1031.             You("feel purified.");
  1032.             if(uasmon == &mons[u.ulycn] && !Polymorph_control)
  1033.             rehumanize();
  1034.         }
  1035.         break;
  1036. #endif
  1037.         case CARROT:
  1038.         make_blinded(0L,TRUE);
  1039.         break;
  1040.         case FORTUNE_COOKIE:
  1041.         outrumor(bcsign(otmp), TRUE);
  1042.         break;
  1043.         case LUMP_OF_ROYAL_JELLY:
  1044.         /* This stuff seems to be VERY healthy! */
  1045.         gainstr(otmp, 1);
  1046.         u.uhp += (otmp->cursed) ? -rnd(20) : rnd(20);
  1047.         if(u.uhp > u.uhpmax) {
  1048.             if(!rn2(17)) u.uhpmax++;
  1049.             u.uhp = u.uhpmax;
  1050.         } else if(u.uhp <= 0) {
  1051.             killer_format = KILLED_BY_AN;
  1052.             killer = "rotten lump of royal jelly";
  1053.             done(POISONING);
  1054.         }
  1055.         if(!otmp->cursed) heal_legs();
  1056.         break;
  1057.         case EGG:
  1058.         if(otmp->corpsenm == PM_COCKATRICE) {
  1059. #ifdef POLYSELF
  1060.             if(!resists_ston(uasmon)) {
  1061. #endif
  1062.             if (!Stoned) Stoned = 5;
  1063.             killer_format = KILLED_BY_AN;
  1064.             killer = "cockatrice egg";
  1065. #ifdef POLYSELF
  1066.             }
  1067. #endif
  1068.         }
  1069.         break;
  1070.     }
  1071.     return;
  1072. }
  1073.  
  1074. int
  1075. doeat() {        /* generic "eat" command funtion (see cmd.c) */
  1076.     register struct obj *otmp;
  1077.     int basenutrit;         /* nutrition of full item */
  1078.  
  1079.     if (Strangled) {
  1080.         pline("If you can't breathe air, how can you consume solids?");
  1081.         return 0;
  1082.     }
  1083.     if (!(otmp = floorfood("eat", 0))) return 0;
  1084. #ifdef POLYSELF
  1085.     /* We have to make non-foods take no time to eat, unless we want to
  1086.      * do ridiculous amounts of coding to deal with partly eaten plate
  1087.      * mails, players who polymorph back to human in the middle of their
  1088.      * metallic meal, etc....
  1089.      */
  1090.     if (!is_edible(otmp)) {
  1091.         You("cannot eat that!");
  1092.         if (otmp->olet == GOLD_SYM) { /* temp gold object */
  1093.         if (otmp->ox) mkgold(OGOLD(otmp), u.ux, u.uy);
  1094.         else u.ugold += OGOLD(otmp);
  1095.         free((genericptr_t) otmp);
  1096.         }
  1097.         return 0;
  1098.     }
  1099.     if (otmp->olet != FOOD_SYM) {
  1100.         victual.reqtime = 1;
  1101.         victual.piece = otmp;
  1102.         /* Don't split it, we don't need to if it's 1 move */
  1103.         victual.usedtime = 0;
  1104.         victual.canchoke = (u.uhs == SATIATED);
  1105.         if (otmp->olet == GOLD_SYM)
  1106.         basenutrit = ((OGOLD(otmp) > 5000L) ? 5000 : (int)OGOLD(otmp));
  1107.         else basenutrit = otmp->owt * 10 / otmp->quan;
  1108.         victual.nmod = basenutrit;
  1109.         victual.eating = TRUE; /* needed for lesshungry() */
  1110.         
  1111.         if (otmp->cursed) 
  1112.         (void) rottenfood(otmp);
  1113.  
  1114.         if (otmp->olet == WEAPON_SYM && otmp->opoisoned) {
  1115.         pline("Ecch - that must have been poisonous!");
  1116.         if(!Poison_resistance) {
  1117.             losestr(rnd(4));
  1118.             losehp(rnd(15), xname(otmp), KILLED_BY_AN);
  1119.         } else
  1120.             You("seem unaffected by the poison.");
  1121.         } else if (!otmp->cursed)
  1122.         pline("This %s is delicious!",
  1123.             otmp->olet == GOLD_SYM ? "gold" : xname(otmp));
  1124.         eatspecial();
  1125.         return 1;
  1126.     }
  1127. #endif
  1128.  
  1129.     if(otmp == victual.piece) {
  1130.     /* If they weren't able to choke, they don't suddenly become able to
  1131.      * choke just because they were interrupted.  On the other hand, if
  1132.      * they were able to choke before, if they lost food it's possible
  1133.      * they shouldn't be able to choke now.
  1134.      */
  1135.         if (u.uhs != SATIATED) victual.canchoke = FALSE;
  1136.         if(!carried(victual.piece)) {
  1137.         if(victual.piece->quan > 1)
  1138.             (void) splitobj(victual.piece, 1);
  1139.         }
  1140.         You("resume your meal.");
  1141.         start_eating(victual.piece);
  1142.         return(1);
  1143.     }
  1144.  
  1145.     /* nothing in progress - so try to find something. */
  1146.     /* tins are a special case */
  1147.     if(otmp->otyp == TIN) {
  1148.         start_tin(otmp);
  1149.         return(1);
  1150.     }
  1151.  
  1152.     victual.piece = otmp = touchfood(otmp);
  1153.     victual.usedtime = 0;
  1154.  
  1155.     /* Now we need to calculate delay and nutritional info.
  1156.      * The base nutrition calculated here and in eatcorpse() accounts
  1157.      * for normal vs. rotten food.  The reqtime and nutrit values are
  1158.      * then adjusted in accordance with the amount of food left.
  1159.      */
  1160.     if(otmp->otyp == CORPSE) {
  1161.         if(eatcorpse(otmp)) return(1);
  1162.         /* else eatcorpse sets up reqtime and oeaten */
  1163.     } else {
  1164.         victual.reqtime = objects[otmp->otyp].oc_delay;
  1165.         if (otmp->otyp != FORTUNE_COOKIE &&
  1166.         (otmp->cursed ||
  1167.          (((monstermoves - otmp->age) > otmp->blessed ? 50 : 30) &&
  1168.         (otmp->orotten || !rn2(7))))) {
  1169.  
  1170. #ifdef POLYSELF
  1171.         if(rottenfood(otmp)) {
  1172. #else
  1173.           if(rottenfood()) {
  1174. #endif
  1175.             otmp->orotten = TRUE;
  1176.             return(1);
  1177.         }
  1178.         otmp->oeaten >>= 1;
  1179.         } else fprefx(otmp);
  1180.     }
  1181.  
  1182.     /* re-calc the nutrition */
  1183.     if (otmp->otyp == CORPSE) basenutrit = mons[otmp->corpsenm].cnutrit;
  1184.     else basenutrit = objects[otmp->otyp].nutrition;
  1185.  
  1186. #ifdef DEBUG
  1187.     debug("before rounddiv: victual.reqtime == %d", victual.reqtime);
  1188.     debug("oeaten == %d, basenutrit == %d", otmp->oeaten, basenutrit);
  1189. #endif
  1190.     victual.reqtime = (basenutrit == 0 ? 0 :
  1191.         rounddiv(victual.reqtime * (long)otmp->oeaten, basenutrit));
  1192. #ifdef DEBUG
  1193.     debug("after rounddiv: victual.reqtime == %d", victual.reqtime);
  1194. #endif
  1195.     /* calculate the modulo value (nutrit. units per round eating)
  1196.      * note: this isn't exact - you actually lose a little nutrition
  1197.      *     due to this method.
  1198.      * TODO: add in a "remainder" value to be given at the end of the
  1199.      *     meal.
  1200.      */
  1201.     if(victual.reqtime == 0)
  1202.         /* possible if most has been eaten before */
  1203.         victual.nmod = 0;
  1204.     else if (otmp->oeaten > victual.reqtime)
  1205.         victual.nmod = -(otmp->oeaten / victual.reqtime);
  1206.     else
  1207.         victual.nmod = victual.reqtime % otmp->oeaten;
  1208.     victual.canchoke = (u.uhs == SATIATED);
  1209.  
  1210.     start_eating(otmp);
  1211.     return(1);
  1212. }
  1213.  
  1214. /* Take a single bite from a piece of food, checking for choking and
  1215.  * modifying usedtime.  Returns 1 if they choked and survived, 0 otherwise.
  1216.  */
  1217. static int
  1218. bite()
  1219. {
  1220.     if(victual.canchoke && u.uhunger >= 2000) {
  1221.         choke(victual.piece);
  1222.         return 1;
  1223.     }
  1224.     if (victual.doreset) {
  1225.         do_reset_eat();
  1226.         return 0;
  1227.     }
  1228.     if(victual.nmod < 0) {
  1229.         lesshungry(-victual.nmod);
  1230.         victual.piece->oeaten -= -victual.nmod;
  1231.     } else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) {
  1232.         lesshungry(1);
  1233.         victual.piece->oeaten--;
  1234.     }
  1235.     recalc_wt();
  1236.     return 0;
  1237. }
  1238.  
  1239. #endif /* OVLB */
  1240. #ifdef OVL0
  1241.  
  1242. void
  1243. gethungry() {        /* as time goes by - called in main.c */
  1244.     --u.uhunger;
  1245.     if(moves % 2) {
  1246.         if(HRegeneration) u.uhunger--;
  1247.         if(Hunger) u.uhunger--;
  1248.         /* a3:  if(Hunger & LEFT_RING) u.uhunger--;
  1249.             if(Hunger & RIGHT_RING) u.uhunger--;
  1250.            etc. */
  1251.     }
  1252.     if(moves % 20 == 0) {            /* jimt@asgb */
  1253.         /* +0 rings don't do anything, so don't affect hunger */
  1254.         if(uleft && uleft->otyp && (!objects[uleft->otyp].oc_charged
  1255.             || uleft->spe)) u.uhunger--;
  1256.         if(uright && uright->otyp && (!objects[uright->otyp].oc_charged
  1257.             || uright->spe)) u.uhunger--;
  1258.         if(uamul) u.uhunger--;
  1259.         if(u.uhave_amulet) u.uhunger--;
  1260.     }
  1261.     newuhs(TRUE);
  1262. }
  1263.  
  1264. #endif /* OVL0 */
  1265. #ifdef OVLB
  1266.  
  1267. void
  1268. morehungry(num)    /* called after vomiting and after performing feats of magic */
  1269. register int num;
  1270. {
  1271.     u.uhunger -= num;
  1272.     newuhs(TRUE);
  1273. }
  1274.  
  1275.  
  1276. void
  1277. lesshungry(num)    /* called after eating (and after drinking fruit juice) */
  1278. register int num;
  1279. {
  1280. #ifdef DEBUG
  1281.     debug("lesshungry(%d)", num);
  1282. #endif
  1283.     u.uhunger += num;
  1284.     if(u.uhunger >= 2000) {
  1285.         if (!victual.eating || victual.canchoke)
  1286.         if (victual.eating) {
  1287.             choke(victual.piece);
  1288.             reset_eat();
  1289.         } else
  1290.             choke((struct obj *) 0);
  1291.             /* no reset_eat(); it was a non-food such as juice */
  1292.     } else {
  1293.         /* Have lesshungry() report when you're nearly full so all eating
  1294.          * warns when you're about to choke.
  1295.          */
  1296.         if (u.uhunger >= 1500) {
  1297.           if(!victual.eating || (victual.eating && !victual.fullwarn)) {
  1298.         pline("You're having a hard time getting all of it down.");
  1299.         nomovemsg = "You're finally finished.";
  1300.         if(!victual.eating)
  1301.             multi = -2;
  1302.         else {
  1303.             victual.fullwarn = TRUE;
  1304.             if (victual.canchoke) {
  1305. #ifdef MACOS
  1306.             if(!flags.silent) SysBeep(20);
  1307.             if(UseMacAlertText(128, "Stop eating ?") == 1)
  1308. #else
  1309.             pline("Stop eating? ");
  1310.             if(yn() == 'y')
  1311. #endif
  1312.                 reset_eat();
  1313.             }
  1314.         }
  1315.           }
  1316.         }
  1317.     }
  1318.     newuhs(FALSE);
  1319. }
  1320.  
  1321. STATIC_PTR
  1322. int
  1323. unfaint() {
  1324.     (void) Hear_again();
  1325.     u.uhs = FAINTING;
  1326.     flags.botl = 1;
  1327.     return 0;
  1328. }
  1329.  
  1330. #endif /* OVLB */
  1331. #ifdef OVL0
  1332.  
  1333. boolean
  1334. is_fainted() {
  1335.     return(u.uhs == FAINTED);
  1336. }
  1337.  
  1338. void
  1339. reset_faint() {    /* call when a faint must be prematurely terminated */
  1340.     if(is_fainted()) nomul(0);
  1341. }
  1342.  
  1343. void
  1344. sync_hunger() {
  1345.  
  1346.     if(is_fainted()) {
  1347.  
  1348.         flags.soundok = 0;
  1349.         nomul(-10+(u.uhunger/10));
  1350.         nomovemsg = "You regain consciousness.";
  1351.         afternmv = unfaint;
  1352.     }
  1353. }
  1354.  
  1355. void
  1356. newuhs(incr)        /* compute and comment on your (new?) hunger status */
  1357.     boolean incr;
  1358. {
  1359.     register int newhs, h = u.uhunger;
  1360.  
  1361.     newhs = (h > 1000) ? SATIATED :
  1362.         (h > 150) ? NOT_HUNGRY :
  1363.         (h > 50) ? HUNGRY :
  1364.         (h > 0) ? WEAK : FAINTING;
  1365.  
  1366.     if(newhs == FAINTING) {
  1367.         if(is_fainted()) newhs = FAINTED;
  1368.         if(u.uhs <= WEAK || rn2(20-u.uhunger/10) >= 19) {
  1369.             if(!is_fainted() && multi >= 0 /* %% */) {
  1370.                 You("faint from lack of food.");
  1371.                 flags.soundok = 0;
  1372.                 nomul(-10+(u.uhunger/10));
  1373.                 nomovemsg = "You regain consciousness.";
  1374.                 afternmv = unfaint;
  1375.                 newhs = FAINTED;
  1376.             }
  1377.         } else
  1378.         if(u.uhunger < -(int)(200 + 20*ACURR(A_CON))) {
  1379.             u.uhs = STARVED;
  1380.             flags.botl = 1;
  1381.             bot();
  1382.             You("die from starvation.");
  1383.             killer_format = KILLED_BY;
  1384.             killer = "starvation";
  1385.             done(STARVING);
  1386.         }
  1387.     }
  1388.  
  1389.     if(newhs != u.uhs) {
  1390.         if(newhs >= WEAK && u.uhs < WEAK)
  1391.             losestr(1);    /* this may kill you -- see below */
  1392.         else if(newhs < WEAK && u.uhs >= WEAK)
  1393.             losestr(-1);
  1394.         switch(newhs){
  1395.         case HUNGRY:
  1396.             if (Hallucination) {
  1397.                 pline((!incr) ?
  1398.                 "You now have a lesser case of the munchies." :
  1399.                 "You are getting the munchies.");
  1400.             } else
  1401.                 You((!incr) ? "only feel hungry now." :
  1402.                   (u.uhunger < 145) ? "feel hungry." :
  1403.                    "are beginning to feel hungry.");
  1404.             break;
  1405.         case WEAK:
  1406.             if (Hallucination)
  1407.                 pline((!incr) ?
  1408.                   "You still have the munchies." :
  1409.       "The munchies are starting to interfere with your motor capabilities.");
  1410.             else
  1411.                 You((!incr) ? "feel weak now." :
  1412.                   (u.uhunger < 45) ? "feel weak." :
  1413.                    "are beginning to feel weak.");
  1414.             break;
  1415.         }
  1416.         u.uhs = newhs;
  1417.         flags.botl = 1;
  1418.         if(u.uhp < 1) {
  1419.             You("die from hunger and exhaustion.");
  1420.             killer_format = KILLED_BY;
  1421.             killer = "exhaustion";
  1422.             done(STARVING);
  1423.         }
  1424.     }
  1425. }
  1426.  
  1427. #endif /* OVL0 */
  1428. #ifdef OVLB
  1429.  
  1430. /* Returns an object representing food.  Object may be either on floor or
  1431.  * in inventory.
  1432.  */
  1433. struct obj *
  1434. floorfood(verb,corpseonly)    /* get food from floor or pack */
  1435.     const char *verb;
  1436.     boolean corpseonly;
  1437. {
  1438.     register struct obj *otmp;
  1439. #ifdef POLYSELF
  1440.     struct gold *gold = g_at(u.ux, u.uy);
  1441.     boolean feeding = (!strcmp(verb, "eat"));
  1442. #endif
  1443. #ifdef POLYSELF
  1444.     if (feeding && gold && metallivorous(uasmon)) {
  1445. #ifdef MACOS
  1446.         char tmp[128];
  1447.         if (gold->amount == 1)
  1448.         Sprintf(tmp, "There is 1 gold piece here. Eat it ?");
  1449.         else Sprintf(tmp, "There are %ld gold pieces here. Eat them ?",
  1450.                                 gold->amount);
  1451.         if(UseMacAlertText(128, tmp) == 1) {
  1452. #else
  1453.         if (gold->amount == 1)
  1454.         pline("There is 1 gold piece here; eat it? ");
  1455.         else pline("There are %ld gold pieces here; eat them? ",
  1456.                                 gold->amount);
  1457.         if (yn() == 'y') {
  1458. #endif
  1459.         otmp = newobj(0);
  1460.         otmp->olet = GOLD_SYM;
  1461.         otmp->ox = u.ux;
  1462.         otmp->oy = u.uy;
  1463.         OGOLD(otmp) = gold->amount;
  1464.         freegold(gold);
  1465.         return otmp;
  1466.         }
  1467.     }
  1468. #endif
  1469.     /* Is there some food (probably a heavy corpse) here on the ground? */
  1470.     if(!Levitation && !u.uswallow) {
  1471.         for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) {
  1472.         if(corpseonly ? otmp->otyp==CORPSE : 
  1473. #ifdef POLYSELF
  1474.             feeding ? is_edible(otmp) :
  1475. #endif
  1476.                         otmp->olet==FOOD_SYM) {
  1477. #ifdef MACOS
  1478.             if(!flags.silent) SysBeep(20);
  1479.         {
  1480.             char tmp[128];
  1481.             Sprintf(tmp, "There %s %s here. %s %s ?",
  1482.                 (otmp->quan == 1) ? "is" : "are",
  1483.                 doname(otmp), verb,
  1484.                 (otmp->quan == 1) ? "it" : "one");
  1485.             if(UseMacAlertText(128, tmp) == 1)
  1486. #else
  1487.             pline("There %s %s here; %s %s? ",
  1488.                 (otmp->quan == 1) ? "is" : "are",
  1489.                 doname(otmp), verb,
  1490.                 (otmp->quan == 1) ? "it" : "one");
  1491.             if(yn() == 'y')
  1492. #endif
  1493.                 return(otmp);
  1494. #ifdef MACOS
  1495.         }
  1496. #endif
  1497.         }
  1498.         }
  1499.     }
  1500. #ifdef POLYSELF
  1501.     /* We cannot use "#" since that causes getobj() to skip its
  1502.      * "ugly checks" and we need to check for inedible items.
  1503.      */
  1504.     return getobj (feeding ? (const char *)everything :
  1505.                  (const char *)comestibles, verb);
  1506. #else
  1507.     return getobj(comestibles, verb);
  1508. #endif
  1509. }
  1510.  
  1511. /* Side effects of vomiting */
  1512. /* added nomul (MRS) - it makes sense, you're too busy being sick! */
  1513. /* TO DO: regurgitate swallowed monsters when poly'd */
  1514. void
  1515. vomit() {        /* A good idea from David Neves */
  1516.     make_sick(0L,TRUE);
  1517.     nomul(-2);
  1518. }
  1519.  
  1520. int
  1521. eaten_stat(base, obj)
  1522. register int base;
  1523. register struct obj *obj;
  1524. {
  1525.     base *= obj->oeaten;
  1526.  
  1527.     if (obj->otyp == CORPSE) 
  1528.         base = mons[obj->corpsenm].cnutrit ?
  1529.                 base / mons[obj->corpsenm].cnutrit : 0;
  1530.     else base = objects[obj->otyp].nutrition ?
  1531.                 base / objects[obj->otyp].nutrition : 0;
  1532.     return (base < 1) ? 1 : base;
  1533. }
  1534.  
  1535. #endif /* OVLB */
  1536.